package com.iteaj.iot.client;

import com.iteaj.iot.client.protocol.ClientSocketProtocol;
import com.iteaj.iot.client.codec.DatagramPacketToMessageDecoder;
import com.iteaj.network.ProtocolException;
import com.iteaj.network.message.UnParseBodyMessage;
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.channel.socket.DatagramPacket;
import io.netty.channel.socket.nio.NioDatagramChannel;

import java.io.IOException;
import java.net.InetSocketAddress;

public abstract class UdpSocketClient extends SocketClient {

    public UdpSocketClient(UdpClientComponent clientComponent) {
        super(clientComponent, null);
    }

    @Override
    protected void doInitOptions(Bootstrap bootstrap) {
        bootstrap.option(ChannelOption.SO_BROADCAST, true);
    }

    @Override
    protected Class<? extends Channel> channel() {
        return NioDatagramChannel.class;
    }

    @Override
    public void doConnect() {
        getBootstrap().bind(0).addListener(future -> {
            connectLogger((ChannelFuture) future);
        });
    }

    @Override
    public void doConnect(long timeout) throws ProtocolException {
        /*doing nothing*/
    }

    @Override
    protected abstract DatagramPacketToMessageDecoder getClientProtocolDecoder();

    /**
     * 写出的报文必须是 UdpRequestProtocol 协议类型
     * @param clientProtocol
     * @return
     */
    @Override
    public ChannelFuture writeAndFlush(ClientSocketProtocol clientProtocol) {
        try {
            // 写入Udp报文 DatagramPacket
            UnParseBodyMessage clientMessage = clientProtocol.requestMessage().build();

            final ByteBuf byteBuf = Unpooled.wrappedBuffer(clientMessage.getMessage());
            final DatagramPacket packet = new DatagramPacket(byteBuf, new InetSocketAddress(getHost(), getPort()));
            clientProtocol.setPacket(packet);

            return super.writeAndFlush(clientProtocol);
        } catch (IOException e) {
            throw new ProtocolException("写udp报文异常", e);
        }
    }
}
